package com.snack.common.utils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class XMLParser
{
	private Document document_;
    private XPath xpath_;

    public XMLParser(String uri) throws SAXException, IOException, ParserConfigurationException
    {        
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        document_ = db.parse(uri);
        
        XPathFactory xpathFactory = XPathFactory.newInstance();
        xpath_ = xpathFactory.newXPath();
    }
    
    public XMLParser(InputStream input) throws ParserConfigurationException, SAXException, IOException
    {        
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        document_ = db.parse(input);
        
        XPathFactory xpathFactory = XPathFactory.newInstance();
        xpath_ = xpathFactory.newXPath();
    }
    
    public XMLParser(File xmlFile) throws ParserConfigurationException, SAXException, IOException
    {        
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        document_ = db.parse(xmlFile);
        
        XPathFactory xpathFactory = XPathFactory.newInstance();
        xpath_ = xpathFactory.newXPath();
    }

	public String getNodeValue(String xql) throws XPathExpressionException
	{
        String value = xpath_.compile(xql).evaluate(document_);
        return "".equals(value) ? null : value;
    }
        
	public String[] getNodeValues(String xql) throws XPathExpressionException
	{
        XPathExpression expr = xpath_.compile(xql);        
        NodeList nl = (NodeList)expr.evaluate(document_, XPathConstants.NODESET);
        int size = nl.getLength();
        String[] values = new String[size];
        
        for ( int i = 0; i < size; ++i )
        {
            Node node = nl.item(i);
            node = node.getFirstChild();
            values[i] = node.getNodeValue();
        }
        return values;       		
	}

	public NodeList getRequestedNodeList(String xql) throws XPathExpressionException
	{
        XPathExpression expr = xpath_.compile(xql);
        NodeList nodeList = (NodeList)expr.evaluate(document_, XPathConstants.NODESET);		
		return nodeList;
	}

	public static String getAttributeValue(Node node, String attrName) throws TransformerException
	{        
		String value = null;
		node = node.getAttributes().getNamedItem(attrName);
		if ( node != null )
		{
		    value = node.getNodeValue();
		}
		return value;
	}
	
	public static XMLParser load(String resource, Class<?> callingClass){
		InputStream input = ClassLoaderUtils.getResourceAsStream(resource,callingClass);
	    return load(input);
	}
	
	public static XMLParser load(InputStream input){
	    try{
            XMLParser xml = new XMLParser(input);
            return xml;
	    }catch(Exception e){
	        throw new RuntimeException(e.getMessage(),e);
	    }finally{
	        try {
                if(input != null)input.close();
            } catch (IOException e) {
            }
	    }
	}
	
	public static XMLParser load(File file){
	    try{
            XMLParser xml = new XMLParser(file);
            return xml;
	    }catch(Exception e){
	        throw new RuntimeException(e.getMessage(),e);
	    }
	}
}
